AddCSLuaFile("cl_init.lua")
AddCSLuaFile("shared.lua")

include('shared.lua')

function ENT:OnRemove()
end

function ENT:KeyValue(key,value)
end

function ENT:Initialize()
	self.Entity:PhysicsInit(SOLID_VPHYSICS)
	self.Entity:SetMoveType(MOVETYPE_FLY)
	self.Entity:SetMoveCollide(MOVECOLLIDE_FLY_SLIDE)
	self.Entity:SetSolid(SOLID_VPHYSICS)
	self.Entity:SetModel("models/weapons/w_bugbait.mdl")
	self.Entity:SetCollisionGroup(COLLISION_GROUP_WEAPON)
	
	self.lastpos = self.Entity:GetPos()
	
	/*
	local list = {
		"models/crow.mdl",
		"models/pigeon.mdl",
	}
	
	self.model = list[math.random(1,#list)]
	
	self.Entity:SetNWString("model",self.model)
	*/
	self.Entity:SetNWEntity("pl",self.Owner)
	self.health = 30
	self.nextcaw = 0
	
	/*
	self.heart = ents.Create("prop_physics")
	local heart = self.heart
	heart:SetModel(Model("models/props_junk/garbage_glassbottle001a.mdl"))
	heart:SetPos(self.Entity:GetPos())
	heart:SetAngles(self.Entity:EyeAngles())
	heart:SetParent(self.Entity)
	heart:SetOwner(self.Entity)
	heart:Spawn()
	heart:CallOnRemove("birdslay",function(_,self)
		if self and IsValid(self.Entity) then
			self:die()
		end
	end)
	*/
	
	//Precache
	Sound("npc/crow/die1.wav")
	Sound("npc/crow/die2.wav")
	Sound("npc/crow/alert2.wav")
	Sound("npc/crow/alert3.wav")
	Sound("npc/crow/idle1.wav")
	Sound("npc/crow/idle2.wav")
	Sound("npc/crow/idle3.wav")
end

function ENT:Use()
end

function ENT:die(nofood)
	local GM = gmod.GetGamemode()
	local pl = self.Owner
	
	if pl and IsValid(pl) and pl:IsPlayer() then
		local uid = pl:UniqueID()
		GM.pldat[uid].pigeon = nil
	end
	
	//TODO: More elaborate death
	
	if not nofood then
		local a = GM:CreateItem("meat")
		if a then
			a:SetPos(self.Entity:GetPos())
			a:SetAngles(self.Entity:EyeAngles())
			a:Spawn()
		end
	end
	
	if not nofood then
		self.Entity:EmitSound(Sound("npc/crow/die"..math.random(1,2)..".wav"))
	end
	self.Entity:Remove()
	if not nofood then
		if IsValid(pl) then
			pl:Kill()
		end
	end
end

function ENT:OnTakeDamage(dmg)
	if IsValid(self) then
		self:die()
	end
end

function ENT:Tick()
	self.Entity:NextThink(CurTime()+0.001)
	if self.Owner and IsValid(self.Owner) and self.Owner:IsPlayer() then
		local pl = self.Owner
		pl:SetPos(self.Entity:GetPos())
		local speed = {
			side = 150,
			fwd = 350,
			bck = -150,
			alt = 250,
		}
		local walkspeed = 9
		local runspeed = 100
		
		local vel = Vector(0,0,0)
		local nokey = true
		
		if not self.unstucking then
			//Calc death
			
			for k,v in pairs(ents.FindInSphere(self.Entity:GetPos(),16)) do
				local killers = {
					ws_item = true,
					ws_arrow = true,
				}
				if v ~= self.Entity and killers[v:GetClass()] and v:GetVelocity():Length() > 1000 then
					self:die()
					if IsValid(self.Owner) and self.Owner:IsPlayer() then
						self.Owner:WSPigeon()
					end
				end
			end
			
			//Calc caw
			if self.nextcaw < CurTime() then
				if pl:KeyDown(IN_ATTACK) then
					self.Entity:EmitSound(Sound("npc/crow/alert"..math.random(2,3)..".wav"))
					self.nextcaw = CurTime() + math.random()*.5+.6
				elseif pl:KeyDown(IN_ATTACK2) then
					self.Entity:EmitSound(Sound("npc/crow/idle"..math.random(1,3)..".wav"))
					self.nextcaw = CurTime() + math.random()*.5+1.5
				end
			end
			
			//Calc move
			if pl:KeyDown(IN_JUMP) then
				nokey = false
				vel = vel + Vector(0,0,1)*speed.alt
				
				if self.lastpos == self.Entity:GetPos() and self.lastjump then
					self.unstucking = ents.Create("prop_physics")
					self.unstucking:SetModel(self.Entity:GetModel())
					self.unstucking:SetPos(self.Entity:GetPos())
					self.unstucking:SetAngles(self.Entity:EyeAngles())
					self.unstucking:SetOwner(self.Entity)
					self.unstucking:Spawn()
					
					Msg("Unstucking ",pl," (",pl:UniqueID(),")...\n")
					
					timer.Simple(.2,function(self)
						self.unstucking:GetPhysicsObject():ApplyForceCenter(Vector(math.random(-400,400),math.random(-400,400),400))
					end,self)
					timer.Simple(.4,function(self)
						self.unstucking:GetPhysicsObject():Sleep()
						local pos = self.unstucking:GetPos()
						self.unstucking:Remove()
						self.unstucking = nil
						self.Entity:SetPos(pos)
						
						Msg("Unstucking ",pl," (",pl:UniqueID(),") iteration complete.\n")
						
						self.unstucking = false
					end,self)
				end
				self.lastjump = true
			else
				self.lastjump = false
			end
			
			if pl:KeyDown(IN_FORWARD) then
				nokey = false
			end
			
			local dist = 16
			local tr = util.TraceLine{
				start = self.Entity:GetPos(),
				endpos = self.Entity:GetPos() - Vector(0,0,dist),
				filter = self.Entity,
			}
			tr.dist = tr.Fraction*dist
			
			if (nokey or tr.Hit) and not pl:KeyDown(IN_JUMP) then //Still or on the ground
				vel = -1*self.Entity:GetVelocity()
				if tr.Hit then //On the ground
					local move = false
					local yaw = nil
					local neg = 1
					if pl:KeyDown(IN_FORWARD) then
						move = true
						yaw = pl:EyeAngles().y
					elseif pl:KeyDown(IN_BACK) then
						move = true
						neg = -1
						yaw = pl:EyeAngles().y+180
					end
					if pl:KeyDown(IN_MOVERIGHT) then
						move = true
						if yaw then
							yaw = yaw-45*neg
						else
							yaw = pl:EyeAngles().y-90
						end
					end
					if pl:KeyDown(IN_MOVELEFT) then
						move = true
						if yaw then
							yaw = yaw+45*neg
						else
							yaw = pl:EyeAngles().y+90
						end
					end
					
					if dist > 12 or dist < 4 then
						self.Entity:SetPos(tr.HitPos+Vector(0,0,8))
					end
					
					if move then
						local dir = tr.HitNormal:Angle()
						local avel = dir:Right():Angle()
						local rot = yaw-avel.y
						avel:RotateAroundAxis(dir:Forward(),rot)
						vel = vel + avel:Forward() * (pl:KeyDown(IN_SPEED) and walkspeed or runspeed)
						//vel = vel + Angle(0,yaw,0):Forward() * walkspeed
					end
					
					//local target = tr.HitPos + Vector(0,0,8)
					//self.Entity:SetPos((target+self.Entity:GetPos())/2)
				end
			else //Lift-off or in the air
				if pl:KeyDown(IN_FORWARD) then
					vel = vel + pl:EyeAngles():Forward() * speed.fwd
				end
				
				self.Entity:SetAngles(pl:EyeAngles())
				vel = vel - self.Entity:GetVelocity()
			end
			self.Entity:SetVelocity(vel)
		end
		
		self.lastpos = self.Entity:GetPos()
	else
		self.Entity:die()
	end
end
hook.Add("Tick","wspigeon",function()
	for k,v in pairs(ents.FindByClass("ws_pigeon")) do
		v:GetTable():Tick()
	end
end)

function ENT:UpdateTransmitState()
	return TRANSMIT_ALWAYS
end
